﻿using HarfBuzzSharp;
using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Runtime;
//using netDxf.Entities;
using SkiaSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace LightCAD.Drawing.Actions
{
    public class DimOrdinateAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;

        static DimOrdinateAction()
        {
            CommandName = "DIMORDINATE";
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "DIMORDINATE",
                Description = "DIMORDINATE",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep{ Name="Step0", Options="指定点坐标:" },
                    new LcCreateStep{ Name="Step1", Options="指定引线端点:" },
                }
            };
            
        }

        internal static void Initilize()
        {
            ElementActions.DimOrdinate = new DimOrdinateAction();
            LcDocument.ElementActions.Add(BuiltinElementType.DimOrdinate, ElementActions.DimOrdinate);
        }

        private PointInputer inputer { get; set; }

        
        private Vector2 startpoint;
        private Vector2 secondpoint;
        private Vector2 endpoint;
      
    
        public DimOrdinateAction() { }
        public DimOrdinateAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令 ：DOR");
        }
        private LcCreateMethod GetMethod(string method)
        {
            if (method == null) return CreateMethods[0];
            var getted= CreateMethods.FirstOrDefault((m) => m.Name == method);
            if (getted == null)
                return CreateMethods[0];
            else
                return getted;
        }
        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            //this.Segments = new List<RolineSegment>();
            var curMethod = CreateMethods[0];
            var ElementInputer = new ElementInputer(this.docEditor);
            this.inputer = new PointInputer(this.docEditor);

            Step0:
            var step0 = curMethod.Steps[0];
            var result0 = await inputer.Execute(step0.Options);
            if (inputer.isCancelled) { this.Cancel(); return; }
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result0.ValueX == null)
            {
                if (result0.Option != null)
                {

                }
                else
                {
                    goto Step1;
                }
            }
            //记住选中点
            this.startpoint = (Vector2)result0.ValueX;
            Step1:
            var step1 = curMethod.Steps[1];
            var result1 = await inputer.Execute(step1.Options);
            if (inputer.isCancelled) { this.Cancel(); return; }
            if (result1 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result1.ValueX == null)
            {
                goto Step1;
            }
            else
            {
                if (result1.Option != null)
                {
                  
                }
                else
                {
                    this.endpoint = (Vector2)result1.ValueX;
                }
            }
          
            CreateDimElement();
            End:
            this.EndCreating();

        }
        private void CreateDimElement()
        {
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("DimOrdinate");
            var DimOrdinate = doc.CreateObject<DimOrdinate>();
            DimOrdinate.Start = this.startpoint;
            DimOrdinate.End = this.endpoint;
            DimOrdinate.Second = this.secondpoint;
            doc.ModelSpace.InsertElement(DimOrdinate);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }
       

     


      
        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }
       
        

        public override void CreateElement(LcElement element, Matrix3 matrix)
        {
            //DocumentManager.CurrentRecorder.BeginAction("Circle");
            //var dim = element as DimDiametric;
            //this.vportRt.ActiveElementSet.AddDimDiametric(matrix.MultiplyPoint(dim.Start), matrix.MultiplyPoint(dim.End),dim.Dimtext);
            //DocumentManager.CurrentRecorder.EndAction();
        }
        public override void CreateElement(LcElement element,Vector2 basePoint, double scaleFactor)
        {
            //var circle = element as LcCircle;
            //Matrix3d matrix3 = Matrix3d.Scale(scaleFactor, basePoint);
            //this.vportRt.ActiveElementSet.AddCircle(matrix3.MultiplyPoint(circle.Center), circle.Radius * scaleFactor);
        }
        public override void CreateElement(LcElement element, Vector2 basePoint, Vector2 scaleVector)
        {
            //var circle = element as LcCircle;
            //Matrix3d matrix3 = Matrix3d.Scale(scaleVector, basePoint);
            //this.vportRt.ActiveElementSet.AddCircle(matrix3.MultiplyPoint(circle.Center), circle.Radius * Vector2d.Distance(basePoint, scaleVector));
        }
        public override void Draw(SKCanvas canvas, LcElement element, Matrix3 matrix)
        {
            var dim = element as DimOrdinate;

            var mstart = matrix.MultiplyPoint(dim.Start);
            var mend = matrix.MultiplyPoint(dim.End);
            var start = this.vportRt.ConvertWcsToScr(mstart).ToSKPoint();
            var end = this.vportRt.ConvertWcsToScr(mend).ToSKPoint();
            #region
            //横线
            LcLine henline = new LcLine();
            //立线
            LcLine liline = new LcLine();

            //判断X Y 的值谁大，谁大先画谁
            double lineX = Math.Abs(dim.End.X - dim.Start.X);
            double lineY = Math.Abs(dim.End.Y - dim.Start.Y);
            if (lineX == 0 || lineY == 0)
            {
                //DrawAuxLine(canvas, startpoint, end.ToVector2d());

            }
            else
            {
                //鼠标移动点与 起始点比较
                if (dim.End.X > dim.Start.X)
                {
                    //表示点在起点右边
                    if (dim.End.Y > dim.Start.Y)
                    {
                        //表示右上
                        Locationline(lineX, lineY, dim.End, dim.Start, "R", "U", out henline, out liline);
                    }
                    else
                    {
                        //表示右下
                        Locationline(lineX, lineY, dim.End, dim.Start, "R", "D", out henline, out liline); ;
                    }
                }
                else
                {
                    //表示点在起点左边
                    if (dim.End.Y > dim.Start.Y)
                    {
                        //表示左上
                        Locationline(lineX, lineY, dim.End, dim.Start, "L", "U", out henline, out liline);
                    }
                    else
                    {
                        //表示左下
                        Locationline(lineX, lineY, dim.End, dim.Start, "L", "D", out henline, out liline);
                    }
                }


                //DrawAuxLine(canvas, henline.Start, henline.End);
                //DrawAuxLine(canvas, liline.Start, liline.End);

            }
            Vector2 vector = new Vector2();
            Vector2 textstart = new Vector2();
            Vector2 textend = new Vector2();
            string textvalue = "";
            double dis = Math.Abs(1000);
           
            if (lineX > lineY)
            {
                //表示文字是延X轴
                //计算向量
                textstart = liline.End;
                vector = new Vector2(henline.End.X - henline.Start.X, henline.End.Y - henline.Start.Y);
                textend = liline.End + (new Vector2(vector.X * dis, vector.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(vector.X, 2.0) + Math.Pow(vector.Y, 2.0))));
                textvalue = dim.Start.Y.ToString("0.00");
            }
            else
            {
                //表示文字延Y轴
                textstart = henline.End;
                vector = new Vector2(liline.End.X - liline.Start.X, liline.End.Y - liline.Start.Y);
                textend = henline.End + (new Vector2(vector.X * dis, vector.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(vector.X, 2.0) + Math.Pow(vector.Y, 2.0))));
                textvalue = dim.Start.X.ToString("0.00");
            }
            var tstart = matrix.MultiplyPoint(textstart);
            var tend = matrix.MultiplyPoint(textend);
            var textstart1 = this.vportRt.ConvertWcsToScr(tstart).ToSKPoint();
            var textend1 = this.vportRt.ConvertWcsToScr(tend).ToSKPoint();

            var hstart = matrix.MultiplyPoint(henline.Start);
            var hend = matrix.MultiplyPoint(henline.End);
            var hstart1 = this.vportRt.ConvertWcsToScr(hstart).ToSKPoint();
            var hend1 = this.vportRt.ConvertWcsToScr(hend).ToSKPoint();

            var lstart = matrix.MultiplyPoint(liline.Start);
            var lend = matrix.MultiplyPoint(liline.End);
            var lstart1 = this.vportRt.ConvertWcsToScr(lstart).ToSKPoint();
            var lend1 = this.vportRt.ConvertWcsToScr(lend).ToSKPoint();
            #endregion

            var pen = this.GetDrawPen(dim);
            
            if (pen == Constants.defaultPen)
            {
                //TODO:这里可以考虑将实线用颜色做KEY，对SKPaint进行缓存
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {
                    canvas.DrawPoint(start, elePen);
                    canvas.DrawLine(hstart1, hend1, elePen);
                    canvas.DrawLine(lstart1, lend1, elePen);
                    canvas.DrawLine(textstart1, textend1,elePen);

                    using (var paint = new SKPaint())
                    {

                        var fontManager = SKFontManager.Default;
                        var emojiTypeface = fontManager.MatchCharacter('时');
                        paint.TextSize = (float)(this.vportRt.Viewport.Scale * 200);
                        //paint.TextAlign = SKTextAlign.Right;
                        paint.IsAntialias = false;
                        paint.Color = new SKColor(0x42, 0x81, 0xA4);
                        paint.IsStroke = false;
                        paint.Typeface = emojiTypeface;

                        var skpath = new SKPath();
                        skpath.MoveTo(textstart1) ;
                        //skpath.LineTo((float)start.X, (float)start.Y);
                        skpath.LineTo(textend1) ;
                        canvas.DrawTextOnPath(textvalue, skpath, 0, 0, paint);


                    }
                    //canvas.DrawLine(start,end, elePen);
                }
            }
            else
            {
                canvas.DrawPoint(start, pen);
                canvas.DrawLine(hstart1, hend1, pen);
                canvas.DrawLine(lstart1, lend1, pen);
                canvas.DrawLine(textstart1, textend1, pen);
                using (var paint = new SKPaint())
                {

                    var fontManager = SKFontManager.Default;
                    var emojiTypeface = fontManager.MatchCharacter('时');
                    paint.TextSize = (float)(this.vportRt.Viewport.Scale * 200);
                    //paint.TextAlign = SKTextAlign.Right;
                    paint.IsAntialias = false;
                    paint.Color = new SKColor(0x42, 0x81, 0xA4);
                    paint.IsStroke = false;
                    paint.Typeface = emojiTypeface;

                    var skpath = new SKPath();
                    skpath.MoveTo(textstart1);
                    //skpath.LineTo((float)start.X, (float)start.Y);
                    skpath.LineTo(textend1);
                    canvas.DrawTextOnPath(textvalue, skpath, 0, 0, paint);


                }
                //canvas.DrawLine(start,end, pen);
            }

        }


        public override void DrawAuxLines(SKCanvas canvas)
        {


            if (startpoint != null)
            {
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);

                //横线
                LcLine henline = new LcLine();
                //立线
                LcLine liline = new LcLine();

                //判断X Y 的值谁大，谁大先画谁
                double lineX = Math.Abs(wcs_mp.X - startpoint.X);
                double lineY = Math.Abs(wcs_mp.Y - startpoint.Y);
                if (lineX == 0 || lineY == 0)
                {
                    DrawAuxLine(canvas, startpoint, wcs_mp);

                }
                else {
                    //鼠标移动点与 起始点比较
                    if (wcs_mp.X > startpoint.X)
                    {
                        //表示点在起点右边
                        if (wcs_mp.Y > startpoint.Y)
                        {
                            //表示右上
                            Locationline(lineX, lineY, wcs_mp, startpoint, "R", "U",out henline, out liline);
                        }
                        else
                        {
                            //表示右下
                            Locationline(lineX, lineY, wcs_mp, startpoint, "R", "D", out henline, out liline);
                        }
                    }
                    else
                    {
                        //表示点在起点左边
                        if (wcs_mp.Y > startpoint.Y)
                        {
                            //表示左上
                            Locationline(lineX, lineY, wcs_mp, startpoint, "L", "U", out henline, out liline);
                        }
                        else
                        {
                            //表示左下
                            Locationline(lineX, lineY, wcs_mp, startpoint, "L", "D", out henline, out liline);
                        }
                    }


                    DrawAuxLine(canvas, henline.Start, henline.End);
                    DrawAuxLine(canvas, liline.Start, liline.End);

                }


              


                //DrawAuxLine(canvas, startpoint, wcs_mp);
            }


        }
        private void DrawAuxLine(SKCanvas canvas, Vector2 p0, Vector2 p1)
        {
            var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(sk_pre, sk_p, Constants.auxElementPen);
            //辅助曲线的颜色，包括辅助长度，辅助角度等
        }

        private void Locationline(double x, double y, Vector2 mp, Vector2 start, string leftOrRight, string upOrDown,out LcLine henline,out LcLine liline) 
        {
            henline = new LcLine();
            liline = new LcLine();

            if (leftOrRight == "R")
            {
                if (upOrDown == "U")
                {
                    //右上
                    if (x > y)
                    {
                        henline.Start = start;
                        henline.End = new Vector2(start.X + x, start.Y);
                       this.secondpoint = henline.End;

                        liline.Start = henline.End;
                        liline.End = mp;

                    }
                    else {
                        liline.Start = start;
                        liline.End = new Vector2(start.X, start.Y + y);
                        this.secondpoint = liline.End;

                        henline.Start = liline.End;
                        henline.End = mp;
                    }
                }
                else 
                {
                    //右下
                    if (x > y)
                    {
                        henline.Start = start;
                        henline.End = new Vector2(start.X + x, start.Y);
                        this.secondpoint = henline.End;

                        liline.Start = henline.End;
                        liline.End = mp;

                    }
                    else
                    {
                        liline.Start = start;
                        liline.End = new Vector2(start.X, start.Y - y);
                        this.secondpoint = liline.End;

                        henline.Start = liline.End;
                        henline.End = mp;
                    }

                }
            }
            else 
            {
                if (upOrDown == "U")
                {
                    //左上
                    if (x > y)
                    {
                        henline.Start = start;
                        henline.End = new Vector2(start.X -x, start.Y);
                        this.secondpoint = henline.End;

                        liline.Start = henline.End;
                        liline.End = mp;

                    }
                    else
                    {
                        liline.Start = start;
                        liline.End = new Vector2(start.X, start.Y + y);
                        this.secondpoint = liline.End;

                        henline.Start = liline.End;
                        henline.End = mp;
                    }
                }
                else 
                {
                    //左下
                    if (x > y)
                    {
                        henline.Start = start;
                        henline.End = new Vector2(start.X - x, start.Y);
                        this.secondpoint = henline.End;

                        liline.Start = henline.End;
                        liline.End = mp;

                    }
                    else
                    {
                        liline.Start = start;
                        liline.End = new Vector2(start.X, start.Y - y);
                        this.secondpoint = liline.End;

                        henline.Start = liline.End;
                        henline.End = mp;
                    }
                }

            }
            
            
        
        }

        #region Grip
        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var dim = element as DimOrdinate;

            var grips = new List<ControlGrip>();
            var gripStartr = new ControlGrip
            {
                Element = dim,
                Name = "Start",
                Position = dim.Start
            };
            grips.Add(gripStartr);

            var gripEnd = new ControlGrip
            {
                Element = dim,
                Name = "End",
                Position = dim.End
            };
            grips.Add(gripEnd);

            return grips.ToArray();
        }
        private string _gripName;
        private Vector2 _position;
        private DimOrdinate _dim;
        private string linttype="";

        public override void SetDragGrip(LcElement element, string gripName, Vector2 position, bool isEnd)
        {
            var dim= element as DimOrdinate;

            _dim = dim;
            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                if (gripName == "Start") 
                {
                   
                    dim.Set (start: _position);

                }
                else
                {
                    dim.Set(end: _position);

                }
            }
        }


        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_dim == null) return;

            var mstart = this.vportRt.ConvertWcsToScr(_dim.Start);
            var mend= this.vportRt.ConvertWcsToScr(_dim.End);
            var mposition = this.vportRt.ConvertWcsToScr(_position);
            if (_gripName == "Start")
            {
                if (_dim.Start.X == _dim.Second.X)
                {
                    //表示竖线
                    //_dim.second.X = _position.X;
                    linttype = "l";
                }
                else if(_dim.Start.Y==_dim.Second.Y) {
                    //_dim.second.Y = _position.Y;
                    linttype = "h";
                }
                Vector2 second=new Vector2();
                if (linttype == "h") {

                     second = new Vector2(_dim.Second.X, _position.Y);
                }  
                else if (linttype == "l")
                {
                     second = new Vector2(_position.X,_dim.Second.Y);
                }
                var msecond = this.vportRt.ConvertWcsToScr(second);
                canvas.DrawLine(mposition.ToSKPoint(), msecond.ToSKPoint(), Constants.draggingPen);
                canvas.DrawLine(msecond.ToSKPoint(), mend.ToSKPoint(), Constants.draggingPen);


            }
            else if(_gripName=="End")
            {
                if (_dim.End.X == _dim.Second.X)
                {
                    //表示竖线
                    //_dim.second.X = _position.X;
                    linttype = "l";
                }
                else if (_dim.End.Y == _dim.Second.Y)
                {
                    //_dim.second.Y = _position.Y;
                    linttype = "h";

                }
                Vector2 second = new Vector2();
                if (linttype == "h")
                {

                    second = new Vector2(_dim.Second.X, _position.Y);
                }
                else if (linttype == "l")
                {
                    second = new Vector2(_position.X, _dim.Second.Y);
                }
                var msecond = this.vportRt.ConvertWcsToScr(second);
                canvas.DrawLine(mstart.ToSKPoint(), msecond.ToSKPoint(), Constants.draggingPen);
                canvas.DrawLine(msecond.ToSKPoint(), mposition.ToSKPoint(), Constants.draggingPen);

            }
            
        }

        #endregion

        public override List<PropertyObserver> GetPropertyObservers()
        {
            return new List<PropertyObserver>();
            
        }
    }
}
